#include "s_catfeed.h"
#include "h_stm32_hal_defines.h"
#include <stdio.h>
#include <string.h>
#include "s_common_message.h"
#include "s_para.h"
#include "s_common_loopClock.h"
#include "s_motor_control.h"
#include "s_lock_buzzer.h"
#include "s_stm32_rtc.h"

#define TEST_CMD		"TEST"

#define STATE_LED 		"LED"
#define STATE_BUZZER	"BUZZER"
#define SYS_UTC			"UTC"
#define RUN_TIME		"RUNTIME"
#define HALT_TIME		"HALTTIME"
#define START_TIME		"STARTTIME"
#define END_TIME		"ENDTIME"

#define MOTOR_PWM		"PWM"
#define SYS_STATE		"STATE"

#define INT_SIZE		4


#define SPLIT_CHAR		':'

static unsigned char stateled_cmd[] = {'L', 'E', 'D', SPLIT_CHAR, 0};
static unsigned char para_error[] = "Para-Error";

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart4;

static unsigned int s_catfeed_sys_state = 0U;

static void s_catfeed_callback_to_run(s_common_loopClock_type type);
static void s_catfeed_callback_to_stop(s_common_loopClock_type type);

void s_catfeed_send_message(const unsigned char *data, unsigned short len)
{
	HAL_UART_Transmit(&huart4 , data, len, 0xFFFF);
}

void s_catfeed_test_callBack(const unsigned char *data, unsigned short len)
{
	// HAL_UART_Transmit(&huart4 , "data", 4, 0xFFFF);
	// HAL_UART_Transmit(&huart1 , "data", 4, 0xFFFF);
	printf("Run here and the len is %d\r\n", len);
}

void s_catfeed_change_state_led_enable(const unsigned char *data, unsigned short len)
{
	unsigned char isEnable;
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(STATE_LED) + 1 + INT_SIZE] = STATE_LED;

	if(data[0] == SPLIT_CHAR) {
		memcpy(&int_value, &data[1], INT_SIZE);

		if(1 == int_value) {
			isEnable = 1;
		} else {
			isEnable = 0U;
			HAL_GPIO_WritePin(STATE_LED_GPIO_Port, STATE_LED_Pin, GPIO_PIN_SET);
		}
		s_para_set_led_enable(isEnable);
	}
	

	send_cmd[STRLEN(STATE_LED)] = SPLIT_CHAR;

	int_value = s_para_get_led_enable();
	memcpy(&send_cmd[STRLEN(STATE_LED) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the led state is %d\r\n", int_value);
}

void s_catfeed_change_state_buzzer_enable(const unsigned char *data, unsigned short len)
{
	unsigned char isEnable;
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(STATE_BUZZER) + 1 + INT_SIZE] = STATE_BUZZER;

	if(data[0] == SPLIT_CHAR) {
		memcpy(&int_value, &data[1], INT_SIZE);
		if(1 == int_value) {
			isEnable = 1;
		} else {
			isEnable = 0U;
			// HAL_GPIO_WritePin(STATE_LED_GPIO_Port, STATE_LED_Pin, GPIO_PIN_SET);
		}
		s_para_set_buzzer_enable(isEnable);
	}
	

	send_cmd[STRLEN(STATE_BUZZER)] = SPLIT_CHAR;

	int_value = s_para_get_buzzer_enable();
	memcpy(&send_cmd[STRLEN(STATE_BUZZER) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the buzzer state is %d\r\n", int_value);
}

void s_catfeed_change_utc(const unsigned char *data, unsigned short len)
{
	// unsigned char isEnable;
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(SYS_UTC) + 1 + INT_SIZE] = SYS_UTC;

	if(data[0] == SPLIT_CHAR) {
		memcpy(&int_value, &data[1], INT_SIZE);
		s_stm32_rtc_set_utc(int_value);
	}
	

	send_cmd[STRLEN(SYS_UTC)] = SPLIT_CHAR;

	int_value = s_stm32_rtc_get_utc();

	memcpy(&send_cmd[STRLEN(SYS_UTC) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the utc is %d\r\n", int_value);

	if(0 == s_catfeed_sys_state) {
		s_catfeed_callback_to_run(s_common_loopClock_default_type);
	} else {
		s_catfeed_callback_to_stop(s_common_loopClock_default_type);
	}
}

void s_catfeed_change_run_time_sec(const unsigned char *data, unsigned short len)
{
	// unsigned char isEnable;
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(RUN_TIME) + 1 + INT_SIZE] = RUN_TIME;

	if(SPLIT_CHAR == data[0]) {
		memcpy(&int_value, &data[1], INT_SIZE);
		s_para_set_run_time_sec(int_value);
	}
	

	send_cmd[STRLEN(RUN_TIME)] = SPLIT_CHAR;

	int_value = s_para_get_run_time_sec();

	memcpy(&send_cmd[STRLEN(RUN_TIME) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the run time is %d\r\n", int_value);


}

void s_catfeed_change_halt_time_sec(const unsigned char *data, unsigned short len)
{
	// unsigned char isEnable;
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(HALT_TIME) + 1 + INT_SIZE] = HALT_TIME;

	if(data[0] == SPLIT_CHAR) {
		memcpy(&int_value, &data[1], INT_SIZE);
		s_para_set_halt_time_sec(int_value);
	}
	

	send_cmd[STRLEN(HALT_TIME)] = SPLIT_CHAR;

	int_value = s_para_get_halt_time_sec();

	memcpy(&send_cmd[STRLEN(HALT_TIME) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the halt time is %d\r\n", int_value);
}

void s_catfeed_change_start_day_time_sec(const unsigned char *data, unsigned short len)
{
	// unsigned char isEnable;
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(START_TIME) + 1 + INT_SIZE] = START_TIME;

	if(data[0] == SPLIT_CHAR) {
		memcpy(&int_value, &data[1], INT_SIZE);
		s_para_set_day_start_time_sec(int_value);
	}
	// memcpy(&int_value, &data[1], INT_SIZE);

	// s_para_set_day_start_time_sec(int_value);

	send_cmd[STRLEN(START_TIME)] = SPLIT_CHAR;

	int_value = s_para_get_day_start_time_sec();

	memcpy(&send_cmd[STRLEN(START_TIME) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the start day time is %d\r\n", int_value);

	if(0 == s_catfeed_sys_state) {
		s_catfeed_callback_to_run(s_common_loopClock_default_type);
	} else {
		s_catfeed_callback_to_stop(s_common_loopClock_default_type);
	}
}

void s_catfeed_change_end_day_time_sec(const unsigned char *data, unsigned short len)
{
	// unsigned char isEnable;
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(END_TIME) + 1 + INT_SIZE] = END_TIME;

	if(data[0] == SPLIT_CHAR) {
		memcpy(&int_value, &data[1], INT_SIZE);
		s_para_set_day_end_time_sec(int_value);
	}
	// memcpy(&int_value, &data[1], INT_SIZE);
	// s_para_set_day_end_time_sec(int_value);

	send_cmd[STRLEN(END_TIME)] = SPLIT_CHAR;

	int_value = s_para_get_day_end_time_sec();

	memcpy(&send_cmd[STRLEN(END_TIME) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the end day time is %d\r\n", int_value);

	if(0 == s_catfeed_sys_state) {
		s_catfeed_callback_to_run(s_common_loopClock_default_type);
	} else {
		s_catfeed_callback_to_stop(s_common_loopClock_default_type);
	}
}

void s_catfeed_pwm_callBack(const unsigned char *data, unsigned short len)
{
	unsigned int int_value;
	unsigned char send_cmd[STRLEN(MOTOR_PWM) + 1 + INT_SIZE] = MOTOR_PWM;

	if(data[0] == SPLIT_CHAR) {
		memcpy(&int_value, &data[1], INT_SIZE);
		s_para_set_motor_pwm(int_value);

		// unsigned char back_power_value = s_motor_control_getPower();
		s_motor_control_setPower((unsigned char)int_value);

		// if(back_power_value == 0) {

		// }
		s_motor_control_start();
		if(0U == s_catfeed_sys_state) {

			vTaskDelay(1000);
			s_motor_control_stop();
		}
	}

	send_cmd[STRLEN(MOTOR_PWM)] = SPLIT_CHAR;

	int_value = s_para_get_motor_pwm();

	memcpy(&send_cmd[STRLEN(MOTOR_PWM) + 1], &int_value, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the pwm is %d\r\n", int_value);



}

void s_catfeed_State_callback(const unsigned char *data, unsigned short len)
{
	unsigned char send_cmd[STRLEN(SYS_STATE) + 1 + INT_SIZE] = SYS_STATE;

	send_cmd[STRLEN(SYS_STATE)] = SPLIT_CHAR;

	memcpy(&send_cmd[STRLEN(SYS_STATE) + 1], &s_catfeed_sys_state, INT_SIZE);
	s_catfeed_send_message(send_cmd, sizeof(send_cmd));

	printf("the state is %d\r\n", s_catfeed_sys_state);
}

static void s_catfeed_callback_to_run(s_common_loopClock_type type)
{
	unsigned int new_hms_sec;
	unsigned int hms_sec_now = s_stm32_rtc_get_hms_sec_now();


	// Normal mode
	if(s_para_get_day_end_time_sec() > s_para_get_day_start_time_sec()) {
		// forbiden time zone
		if(hms_sec_now < s_para_get_day_start_time_sec()) {
			new_hms_sec = s_para_get_day_start_time_sec() - hms_sec_now;
		} else if(hms_sec_now > s_para_get_day_end_time_sec()) {
			new_hms_sec = 24 * 3600 - hms_sec_now + s_para_get_day_start_time_sec();
		} else {
			new_hms_sec = s_para_get_halt_time_sec();
		}
	} else {
		// un normal mode
		if(hms_sec_now > s_para_get_day_start_time_sec()) {
			new_hms_sec = s_para_get_halt_time_sec();
		} else {
			new_hms_sec = s_para_get_halt_time_sec();
			if(hms_sec_now > s_para_get_day_end_time_sec()) {
				if(hms_sec_now + s_para_get_halt_time_sec() > s_para_get_day_start_time_sec()) {
					new_hms_sec = s_para_get_day_start_time_sec() - hms_sec_now;
				}
			}
		}
	}

    if(s_para_get_buzzer_enable()) {
    	S_Lock_Buzzer_DeSuccess();
    }

    // new_hms_sec = 10;
    printf("s_catfeed_callback_to_run: %d\r\n", new_hms_sec);
    s_motor_control_stop();

    s_catfeed_sys_state = 0U;

    s_common_loopClock_specialEvt_edit_time(2, new_hms_sec);
	s_common_loopClock_specialEvt_start(2);

}

static void s_catfeed_callback_to_stop(s_common_loopClock_type type)
{
	unsigned int new_hms_sec;
	unsigned int hms_sec_now = s_stm32_rtc_get_hms_sec_now();
	
	// Normal mode
	if(s_para_get_day_end_time_sec() > s_para_get_day_start_time_sec()) {
		// forbiden time zone
		if(hms_sec_now < s_para_get_day_start_time_sec() || hms_sec_now > s_para_get_day_end_time_sec()) {
			printf("hms now is %d, start is %d, end is %d\r\n", hms_sec_now, s_para_get_day_start_time_sec(), s_para_get_day_end_time_sec());
			printf("normal mode but forbiden\r\n");
			if(hms_sec_now < s_para_get_day_start_time_sec()) {
				new_hms_sec = s_para_get_day_start_time_sec() - hms_sec_now;
			} else {
				new_hms_sec = 24 * 3600 - hms_sec_now + s_para_get_day_start_time_sec();
			}

			printf("check next run %d\r\n", new_hms_sec);
			s_common_loopClock_specialEvt_edit_time(2, new_hms_sec);
			s_common_loopClock_specialEvt_start(2);

			return;
		} else {
			if(hms_sec_now + s_para_get_run_time_sec() > s_para_get_day_end_time_sec()) {
				new_hms_sec = s_para_get_day_end_time_sec() - hms_sec_now;
			} else {
				new_hms_sec = s_para_get_run_time_sec();
			}
		}
	} else {
		// un normal mode
		if(hms_sec_now > s_para_get_day_start_time_sec()) {
			new_hms_sec = s_para_get_run_time_sec();
			if(hms_sec_now + s_para_get_run_time_sec() > 24 * 3600) {
				if(hms_sec_now + s_para_get_run_time_sec() - 24 * 3600 > s_para_get_day_end_time_sec()) {
					// run too long
					new_hms_sec = 24 * 3600 - hms_sec_now + s_para_get_day_end_time_sec();
				}
			}
		} else {
			if(hms_sec_now > s_para_get_day_end_time_sec()) {
				// Forbiden time zone
				printf("un normal mode but forbiden: now:%d-start:%d-end:%d\r\n", hms_sec_now, s_para_get_day_start_time_sec(), s_para_get_day_end_time_sec());
				
				// if(hms_sec_now < s_para_get_day_start_time_sec()) {
					new_hms_sec = s_para_get_day_start_time_sec() - hms_sec_now;
				// } else {

				// }
				

				printf("check next run %d\r\n", new_hms_sec);
				s_common_loopClock_specialEvt_edit_time(2, new_hms_sec);
				s_common_loopClock_specialEvt_start(2);

				return;
			} else {
				if(hms_sec_now + s_para_get_run_time_sec() > s_para_get_day_end_time_sec()) {
					new_hms_sec = s_para_get_day_end_time_sec() - hms_sec_now;
				} else {
					new_hms_sec = s_para_get_run_time_sec();
				}
			}
		}
	}

	if(s_para_get_buzzer_enable()) {
		S_Lock_Buzzer_Success();
	}
	printf("s_catfeed_callback_to_stop: %d\r\n", new_hms_sec);

	s_motor_control_setPower((unsigned char)s_para_get_motor_pwm());
	s_motor_control_start();

	s_catfeed_sys_state = 1U;

	s_common_loopClock_specialEvt_edit_time(1, new_hms_sec);
	s_common_loopClock_specialEvt_start(1);
}

// #define STATE_LED 		"LED"
// #define STATE_BUZZER	"BUZZER"
// #define SYS_UTC			"UTC"
// #define RUN_TIME		"RUNTIME"
// #define HALT_TIME		"HALTTIME"
// #define START_TIME		"STARTTIME"
// #define END_TIME		"ENDTIME"
void s_catfeed_init(void)
{
	s_common_message_init();
	s_common_loopClock_init();

	s_motor_control_setPower(90);

	printf("Add test rslt %d\r\n", s_common_message_add(TEST_CMD, STRLEN(TEST_CMD), &s_catfeed_test_callBack));
	printf("Add led rslt %d\r\n", s_common_message_add(STATE_LED, STRLEN(STATE_LED), &s_catfeed_change_state_led_enable));
	printf("Add buzzer rslt %d\r\n", s_common_message_add(STATE_BUZZER, STRLEN(STATE_BUZZER), &s_catfeed_change_state_buzzer_enable));
	printf("Add utc rslt %d\r\n", s_common_message_add(SYS_UTC, STRLEN(SYS_UTC), &s_catfeed_change_utc));

	printf("Add run rslt %d\r\n", s_common_message_add(RUN_TIME, STRLEN(RUN_TIME), &s_catfeed_change_run_time_sec));
	printf("Add halt rslt %d\r\n", s_common_message_add(HALT_TIME, STRLEN(HALT_TIME), &s_catfeed_change_halt_time_sec));
	printf("Add start rslt %d\r\n", s_common_message_add(START_TIME, STRLEN(START_TIME), &s_catfeed_change_start_day_time_sec));
	printf("Add end rslt %d\r\n", s_common_message_add(END_TIME, STRLEN(END_TIME), &s_catfeed_change_end_day_time_sec));

	printf("Add pwm rslt %d\r\n", s_common_message_add(MOTOR_PWM, STRLEN(MOTOR_PWM), &s_catfeed_pwm_callBack));
	printf("Add sys-state rslt %d\r\n", s_common_message_add(SYS_STATE, STRLEN(SYS_STATE), &s_catfeed_State_callback));

	s_common_loopClock_specialEvt_add(1, s_catfeed_callback_to_run, s_para_get_run_time_sec()); //600s
	s_common_loopClock_specialEvt_add(2, s_catfeed_callback_to_stop, s_para_get_halt_time_sec()); //3600s

	// first run
	s_catfeed_callback_to_stop(s_common_loopClock_default_type);

	// s_motor_control_start();

	// if(s_para_get_buzzer_enable()) {
	// 	S_Lock_Buzzer_Success();
	// }

	// s_common_loopClock_specialEvt_start(1);
}